/**
 * Copyright(c) 2013 Jade Techonologies Co., Ltd.
 *
 * History:
 *   14-7-29 下午1:14 Created by dwzhang
 */
package com.jade.framework.base.comm;

import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * 抽象的服务器端实现。
 *
 * @author dwzhang
 * @version 1.0 14-7-29 下午1:14
 */
public abstract class AbstractServer<Channel>
        implements CommServer<Channel>
{
    protected Protocol protocol;
    protected Map<InetSocketAddress, ProtocolSession> sessionMap;
    protected boolean started;

    public void setProtocol(Protocol protocol)
    {
        this.protocol = protocol;
    }

    public boolean isStarted()
    {
        return started;
    }

    public boolean isStopped()
    {
        return !started;
    }

    public void start()
    {
        protocol.getLog().info("Start netty common server ......");
        sessionMap = new HashMap<InetSocketAddress, ProtocolSession>();
        try {
            doStart();
            protocol.getLog().info("It's successful to start netty common server!");
            started = true;
        }
        catch (Throwable t) {
            protocol.getLog().error("start server error:", t);
        }
    }

    protected abstract void doStart()
            throws CommException;

    public void stop()
    {
        protocol.getLog().info("Stop netty common server ......");
        if (sessionMap != null) {
            Set<InetSocketAddress> addrs = sessionMap.keySet();
            for (InetSocketAddress addr : addrs) {
                ProtocolSession session = sessionMap.get(addr);
                closeSession(session);
            }
            sessionMap.clear();
        }
        doStop();
        protocol.getLog().info("It's successful to stop netty common server!");
        started = false;
    }

    protected abstract void doStop();

    protected void closeSession(ProtocolSession session)
    {
        ProtocolTransport transport = session.getTransport();
        if (transport.isAlive()) {
            transport.close();
        }
    }

    public Collection<ProtocolSession> getSessions()
    {
        return sessionMap == null ? null : sessionMap.values();
    }

    public ProtocolSession getSession(InetSocketAddress address)
    {
        return sessionMap == null ? null : sessionMap.get(address);
    }

    public void addSession(ProtocolSession session)
    {
        if (!started) {
            throw new IllegalStateException("Server not started");
        }
        sessionMap.put(session.getRemoteAddress(), session);
    }

    public void removeSession(ProtocolSession session)
    {
        if (sessionMap != null) {
            sessionMap.remove(session.getRemoteAddress());
        }
    }

}
